// Minutes2Midnight.cpp : Defines the entry point for the application.
//

#include "stdafx.h"
#include "Minutes2Midnight.h"

// These defines declare the colour of each
// region of the user interface
#define SHADE_TOP	 RGB(247, 248, 193)
#define SHADE_MIDDLE RGB(187, 213, 172)
#define SHADE_BOTTOM RGB(126, 177, 150)

// Various timeframes expressed in units
// of 100-nanosecond intervals.
#define ONE_SECOND ((__int64)10000000)
#define ONE_MINUTE ((__int64)(ONE_SECOND * 60))
#define ONE_HOUR   ((__int64)(ONE_MINUTE * 60))
#define ONE_DAY    ((__int64)(ONE_HOUR * 24))

INT_PTR CALLBACK MinutesToMidnightDialog(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
	HWND hWndCtrl;

    switch (message)
    {
        case WM_INITDIALOG:
            {
                // Initialise the dialog with an (OK) button and an empty menubar
                SHINITDLGINFO shidi;
                shidi.dwMask = SHIDIM_FLAGS;
                shidi.dwFlags = SHIDIF_DONEBUTTON | SHIDIF_SIPDOWN | SHIDIF_SIZEDLGFULLSCREEN | SHIDIF_EMPTYMENU;
                shidi.hDlg = hDlg;
                SHInitDialog(&shidi);

				// Setup the range and current value of each progress bar
				hWndCtrl = GetDlgItem(hDlg, IDC_PROGRESS_TOTAL);
				SendMessage(hWndCtrl, PBM_SETRANGE32, 0, 86400);
				SendMessage(hWndCtrl, PBM_SETPOS,  0, 0);

				hWndCtrl = GetDlgItem(hDlg, IDC_PROGRESS_HOURS);
				SendMessage(hWndCtrl, PBM_SETRANGE, 0, MAKELPARAM(0, 24));
				SendMessage(hWndCtrl, PBM_SETPOS,  0, 0);

				hWndCtrl = GetDlgItem(hDlg, IDC_PROGRESS_MINUTES);
				SendMessage(hWndCtrl, PBM_SETRANGE, 0, MAKELPARAM(0, 60));
				SendMessage(hWndCtrl, PBM_SETPOS,  0, 0);

				hWndCtrl = GetDlgItem(hDlg, IDC_PROGRESS_SECONDS);
				SendMessage(hWndCtrl, PBM_SETRANGE, 0, MAKELPARAM(0, 60));
				SendMessage(hWndCtrl, PBM_SETPOS,  0, 0);

				hWndCtrl = GetDlgItem(hDlg, IDC_PROGRESS_TOTAL_MINUTES);
				SendMessage(hWndCtrl, PBM_SETRANGE, 0, MAKELPARAM(0, 1440));
				SendMessage(hWndCtrl, PBM_SETPOS,  0, 0);

				hWndCtrl = GetDlgItem(hDlg, IDC_PROGRESS_TOTAL_SECONDS);
				SendMessage(hWndCtrl, PBM_SETRANGE32, 0, 86400); // [CF] - TODO - notice trap... need to use PBM_SETRANGE32 not PBM_SETRANGE due to 86400 being greather than 16bit...

				// Start a timer to refresh the UI once a second
				SetTimer(hDlg, 1, 1000, NULL);
			}
            return (INT_PTR)TRUE;

		case WM_PAINT:
			{
				// Paint the background of the dialog
				RECT rcBounds, rcCtrl, rcCtrl2;
				HBRUSH hbrNew;
				HWND hWnd;
				PAINTSTRUCT ps;

				HDC hdc = BeginPaint(hDlg, &ps);

				GetClientRect(hDlg, &rcBounds);

				// Top
				hWnd = GetDlgItem(hDlg, IDC_STATIC_HOURS);
				GetClientRect(hWnd, &rcCtrl);
				MapWindowPoints(hWnd, hDlg, (LPPOINT)&rcCtrl, 2);
				
				rcCtrl.bottom = rcCtrl.top;
				rcCtrl.top = 0;
				rcCtrl.left = 0;
				rcCtrl.right = rcBounds.right;

				hbrNew = CreateSolidBrush(SHADE_TOP);
				FillRect(hdc, &rcCtrl, hbrNew);
				DeleteObject(hbrNew);

				// Middle
				hWnd = GetDlgItem(hDlg, IDC_STATIC_TOTAL_MINUTES);
				GetClientRect(hWnd, &rcCtrl2);
				MapWindowPoints(hWnd, hDlg, (LPPOINT)&rcCtrl2, 2);

				rcCtrl.top = rcCtrl.bottom;
				rcCtrl.bottom = rcCtrl2.top;

				hbrNew = CreateSolidBrush(SHADE_MIDDLE);
				FillRect(hdc, &rcCtrl, hbrNew);
				DeleteObject(hbrNew);

				// Bottom
				rcCtrl.top = rcCtrl.bottom;
				rcCtrl.bottom = rcBounds.bottom;

				hbrNew = CreateSolidBrush(SHADE_BOTTOM);
				FillRect(hdc, &rcCtrl, hbrNew);
				DeleteObject(hbrNew);

				EndPaint(hDlg, &ps);
			}
			return TRUE;

		case WM_CTLCOLORSTATIC:
			{
				// Alter the background colour of the
				// labels
				int id = GetWindowLong((HWND)lParam, GWL_ID);
				if (id == IDC_STATIC_HOURS || id == IDC_STATIC_MINUTES || id == IDC_STATIC_SECONDS)
				{
					HBRUSH brush = CreateSolidBrush(SHADE_MIDDLE);
					SetBkMode((HDC)wParam, TRANSPARENT);
					return (INT_PTR)brush;
				}
				else if (id == IDC_STATIC_TOTAL_MINUTES || id == IDC_STATIC_TOTAL_SECONDS)
				{
					HBRUSH brush = CreateSolidBrush(SHADE_BOTTOM);
					SetBkMode((HDC)wParam, TRANSPARENT);
					return (INT_PTR)brush;
				}
			}
			break;

		case WM_TIMER:
			{
				SYSTEMTIME time;
				FILETIME ft;
				TCHAR szBuffer[64];
				__int64 diff;

				int hours, minutes, seconds, totalseconds;
				double totalminutes;

				// Calculate how much of the current day is left
				GetLocalTime(&time);
				SystemTimeToFileTime(&time, &ft);
				diff = ONE_DAY - ((*(__int64*)&ft) % ONE_DAY);

				// Turn that into the number of hours, minutes and seconds
				hours = (int)(diff / ONE_HOUR);
				minutes = (int)(diff / ONE_MINUTE) % 60;
				seconds = (int)(diff / ONE_SECOND) % 60;
				totalminutes = (diff / (double)ONE_MINUTE);
				totalseconds = (int)(diff / ONE_SECOND);

				// Update the various progress bars and status labels
				hWndCtrl = GetDlgItem(hDlg, IDC_PROGRESS_TOTAL);
				SendMessage(hWndCtrl, PBM_SETPOS, 86400 - totalseconds, 0);

				hWndCtrl = GetDlgItem(hDlg, IDC_PROGRESS_HOURS);
				SendMessage(hWndCtrl, PBM_SETPOS, 24 - hours, 0);
				_stprintf(szBuffer, L"%ld of 24 hours left", hours);
				SetDlgItemText(hDlg, IDC_STATIC_HOURS, szBuffer);

				hWndCtrl = GetDlgItem(hDlg, IDC_PROGRESS_MINUTES);
				SendMessage(hWndCtrl, PBM_SETPOS, 60 - minutes, 0);
				_stprintf(szBuffer, L"%ld of 60 minutes left", minutes);
				SetDlgItemText(hDlg, IDC_STATIC_MINUTES, szBuffer);

				hWndCtrl = GetDlgItem(hDlg, IDC_PROGRESS_SECONDS);
				SendMessage(hWndCtrl, PBM_SETPOS, 60 - seconds, 0);
				_stprintf(szBuffer, L"%ld of 60 seconds left", seconds);
				SetDlgItemText(hDlg, IDC_STATIC_SECONDS, szBuffer);

				hWndCtrl = GetDlgItem(hDlg, IDC_PROGRESS_TOTAL_MINUTES);
				SendMessage(hWndCtrl, PBM_SETPOS, 1440 - totalminutes, 0);
				_stprintf(szBuffer, L"%0.1f of 1440 total minutes left", totalminutes);
				SetDlgItemText(hDlg, IDC_STATIC_TOTAL_MINUTES, szBuffer);

				hWndCtrl = GetDlgItem(hDlg, IDC_PROGRESS_TOTAL_SECONDS);
				SendMessage(hWndCtrl, PBM_SETPOS, 86400 - totalseconds, 0);
				_stprintf(szBuffer, L"%ld of 86400 total seconds left", totalseconds);
				SetDlgItemText(hDlg, IDC_STATIC_TOTAL_SECONDS, szBuffer);
			}
			break;

        case WM_COMMAND:
            if (LOWORD(wParam) == IDOK)
            {
                EndDialog(hDlg, LOWORD(wParam));
                return (INT_PTR)TRUE;
            }
            break;

        case WM_CLOSE:
            EndDialog(hDlg, message);
            return (INT_PTR)TRUE;

    }
    return (INT_PTR)FALSE;
}

int WINAPI WinMain(HINSTANCE hInstance,
                   HINSTANCE hPrevInstance,
                   LPTSTR    lpCmdLine,
                   int       nCmdShow)
{
	INITCOMMONCONTROLSEX InitCtrlEx;

	InitCtrlEx.dwSize = sizeof(INITCOMMONCONTROLSEX);
	InitCtrlEx.dwICC  = ICC_PROGRESS_CLASS;
	InitCommonControlsEx(&InitCtrlEx);

	return DialogBox(hInstance, (LPCTSTR)IDD_MINUTES2MIDNIGHT, NULL, MinutesToMidnightDialog);
}